#include <assert.h>

#include "debug_utils.h"
#include "student_interface.h"
#include "student_service.h"

/**
 * Initialize the student service context.
 */

status_t service_init_student(service_student_context_t *context,
                              student_interface_t *interface)
{
        assert(context != NULL);
        assert(interface != NULL);

        student_interface_init(interface);

        context->student_interface = interface;

        DEBUG_PRINT("Initialized student service with context=%p and "
                    "interface=%p\n",
                    (void *)context, (void *)interface);

        return STATUS_SUCCESS;
}

/**
 * Add a student.
 */
status_t service_add_student(service_student_context_t *context,
                             const student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.add_student_fn != NULL);
        assert(info != NULL);

        DEBUG_PRINT("Adding student with ID=%s\n", info->id);

        return context->student_interface->management.add_student_fn(info);
}

/**
 * Delete a student by id.
 */
status_t service_delete_student_id(service_student_context_t *context,
                                   const char *id,
                                   student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.delete_student_id_fn != NULL);
        assert(id != NULL);
        assert(info != NULL);

        DEBUG_PRINT("Deleting student with ID=%s\n", id);

        return context->student_interface->management.delete_student_id_fn(id, info);
}

/**
 * Delete a student by name.
 */
status_t service_delete_student_name(service_student_context_t *context,
                                     const char *name,
                                     student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.delete_student_name_fn != NULL);
        assert(name != NULL);
        assert(info != NULL);

        DEBUG_PRINT("Deleting student with name=%s\n", name);

        return context->student_interface->management.delete_student_name_fn(name, info);
}

/**
 * Update a student's information.
 */
status_t service_update_student(service_student_context_t *context,
                                const student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.update_student_fn != NULL);
        assert(info != NULL);

        DEBUG_PRINT("Updating student with ID=%s\n", info->id);

        return context->student_interface->management.update_student_fn(info);
}

/**
 * Query a student by id.
 */
status_t service_query_student_id(service_student_context_t *context,
                                  const char *id,
                                  student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.query_student_id_fn != NULL);
        assert(id != NULL);

        DEBUG_PRINT("Querying student with ID=%s\n", id);

        return context->student_interface->management.query_student_id_fn(id, info);
}

/**
 * Query a student by name.
 */
status_t service_query_student_name(service_student_context_t *context,
                                    const char *name,
                                    student_info_t *info)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.query_student_name_fn != NULL);
        assert(name != NULL);

        DEBUG_PRINT("Querying student with name=%s\n", name);

        return context->student_interface->management.query_student_name_fn(name, info);
}

/**
 * Get all students.
 */
status_t service_get_all_student(service_student_context_t *context,
                                 student_info_t **students,
                                 size_t *count)
{
        assert(context != NULL);
        assert(context->student_interface != NULL);
        assert(context->student_interface->management.get_all_students_fn != NULL);
        assert(students != NULL);
        assert(count != NULL);

        status_t status = context->student_interface->management.get_all_students_fn(students, count);

        if (status != STATUS_SUCCESS)
                return status;

        return STATUS_SUCCESS;
}
